using Net.Component;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;

namespace Net.AI
{
    public class Pathfinding : SingleCase<Pathfinding>
    {
        public RcdtcsUnityUtils.RecastMeshParams m_NavMeshParams = new RcdtcsUnityUtils.RecastMeshParams();
        private RcdtcsUnityUtils.SystemHelper m_System = new RcdtcsUnityUtils.SystemHelper();
        private DbgRenderMesh m_DbgRenderMesh = new DbgRenderMesh();
        public Material m_DebugRenderMeshMaterial = null;
        private RcdtcsUnityUtils.StraightPath m_StraightPath = null;
        public LayerMask layerMask;

        void Start()
        {
            Load();
        }

        public void Load()
        {
            var data = new MeshData();
            using (var stream = new FileStream(Application.dataPath + "/navData.map", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                var bytes = new byte[1024];
                stream.Read(bytes, 0, 4);
                data.vertexCount = BitConverter.ToInt32(bytes);
                stream.Read(bytes, 0, 4);
                var trianglesCount = BitConverter.ToInt32(bytes);
                data.triangles = new int[trianglesCount];
                bytes = new byte[trianglesCount * 4];
                stream.Read(bytes, 0, bytes.Length);
                for (int i = 0; i < trianglesCount; i++)
                {
                    data.triangles[i] = BitConverter.ToInt32(bytes, i * 4);
                }
                stream.Read(bytes, 0, 4);
                var verticesCount = BitConverter.ToInt32(bytes);
                data.vertices = new Net.Vector3[verticesCount];
                bytes = new byte[verticesCount * 12];
                stream.Read(bytes, 0, bytes.Length);
                for (int i = 0; i < verticesCount; i++)
                {
                    var x = BitConverter.ToSingle(bytes, i * 12);
                    var y = BitConverter.ToSingle(bytes, i * 12 + 4);
                    var z = BitConverter.ToSingle(bytes, i * 12 + 8);
                    data.vertices[i] = new Net.Vector3(x, y, z);
                }
            }

            //if (m_DebugRenderMeshMaterial == null)
            //{
            //    Shader vertexColor = Shader.Find("Custom/VertexColorShader");
            //    m_DebugRenderMeshMaterial = new Material(vertexColor);
            //}

            //m_DbgRenderMesh.CreateGameObject("Dbg Render Mesh", m_DebugRenderMeshMaterial);

            m_System.SetNavMeshParams(m_NavMeshParams);
            m_System.ClearComputedData();
            m_System.ClearMesh();

            m_System.AddMesh(data, transform.gameObject);

            m_System.ComputeSystem();

            m_DbgRenderMesh.Mesh = new Mesh();
            RcdtcsUnityUtils.ShowRecastNavmesh(m_DbgRenderMesh, m_System.m_pmesh, m_System.m_cfg);
        }

        public void Save()
        {
            var mesh = Merge();
            var data = new MeshData(mesh);
            using (var stream = new FileStream(Application.dataPath + "/navData.map", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Seek(0, SeekOrigin.Begin);
                stream.SetLength(0);
                stream.Write(BitConverter.GetBytes(data.vertexCount));
                stream.Write(BitConverter.GetBytes(data.triangles.Length));
                foreach (var tri in data.triangles)
                    stream.Write(BitConverter.GetBytes(tri));
                stream.Write(BitConverter.GetBytes(data.vertices.Length));
                foreach (var ver in data.vertices)
                {
                    stream.Write(BitConverter.GetBytes(ver.x));
                    stream.Write(BitConverter.GetBytes(ver.y));
                    stream.Write(BitConverter.GetBytes(ver.z));
                }
                stream.Flush();
            }
        }

        private Mesh Merge()
        {
            //获取所有子物体的网格过滤器组件
            MeshFilter[] meshFilters = FindObjectsOfType<MeshFilter>(true).Where(mf => ((1 << mf.gameObject.layer) & layerMask) > 0).ToArray();

            //创建一个新的合并后的网格
            Mesh mergedMesh = new Mesh();

            //创建一个合并用的网格数组
            CombineInstance[] combine = new CombineInstance[meshFilters.Length];

            for (int i = 0; i < meshFilters.Length; i++)
            {
                //设置合并用的网格数组
                combine[i].mesh = meshFilters[i].sharedMesh;
                combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
            }

            //合并网格
            mergedMesh.CombineMeshes(combine);

            return mergedMesh;
        }

        public List<Vector3> GetPath(Vector3 currPosition, Vector3 destination)
        {
            var paths = new List<Vector3>();
            GetPath(currPosition, destination, paths);
            return paths;
        }

        public void GetPath(Vector3 currPosition, Vector3 destination, List<Vector3> paths)
        {
            m_StraightPath = RcdtcsUnityUtils.ComputeStraightPath(m_System.m_navQuery, currPosition, destination);
            var path = m_StraightPath.m_straightPath;
            paths.Clear();
            if (path != null && path.Length > 3)
            {
                var vertCount = m_StraightPath.m_straightPathCount;
                for (int i = 1; i < vertCount; ++i)
                {
                    int v = i * 3;
                    var a = new Vector3(path[v - 3], path[v - 2], path[v - 1]);
                    var b = new Vector3(path[v + 0], path[v + 1], path[v + 2]);
                    paths.Add(a);
                    paths.Add(b);
                }
            }
        }

        private void OnDrawGizmos()
        {
            if (m_DbgRenderMesh.Mesh == null)
                return;
            Gizmos.color = new Color(0f, 1f, 1f, 0.5f);
            Gizmos.DrawMesh(m_DbgRenderMesh.Mesh);
            Gizmos.color = new Color(0f, 0f, 0f, 0.3f);
            Gizmos.DrawWireMesh(m_DbgRenderMesh.Mesh);
        }
    }
}